package com.rj.core.check;

import cn.hutool.core.text.StrFormatter;
import com.rj.core.exception.AssertException;
import com.rj.util.AssertUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * @param <T>
 * @author Administrator
 */
public class AssertorBean<T> {
    /**
     * 校验对象
     */
    private T bean;
    /**
     * 是否抛出异常
     */
    private boolean isThrow = true;
    /**
     * 标签说明
     */
    private String label;
    /**
     * 校验结果存储器
     */
    private List<String> messages = new ArrayList<String>();

    /**
     * 获取字段校验器
     *
     * @param value
     * @param title
     * @param <V>
     * @param <R>
     * @return
     */
    public <V, R> AssertFiledValue<T, V, R> field(V value, String title, boolean allowEmpty) {
        return new AssertFiledValue<T, V, R>().read(value, title, this, allowEmpty, null);
    }

    /**
     * 获取字段校验器
     *
     * @param value
     * @param title
     * @param <V>
     * @param <R>
     * @return
     */
    public <V, R> AssertFiledValue<T, V, R> field(V value, String title, boolean allowEmpty, Integer maxLen) {
        return new AssertFiledValue<T, V, R>().read(value, title, this, allowEmpty, maxLen);
    }

    /**
     * 获取字段校验器
     *
     * @param getter
     * @param title
     * @param <V>
     * @param <R>
     * @return
     */
    public <V, R> AssertFiledValue<T, V, R> field(SFunction<T, V> getter, String title, boolean allowEmpty) {
        V apply = getter.apply(bean);
        return new AssertFiledValue<T, V, R>().read(apply, title, this, allowEmpty, null);
    }

    /**
     * 获取字段校验器
     *
     * @param getter
     * @param title
     * @param <V>
     * @param <R>
     * @return
     */
    public <V, R> AssertFiledValue<T, V, R> field(SFunction<T, V> getter, String title, boolean allowEmpty, Integer maxLen) {
        V apply = getter.apply(bean);
        return new AssertFiledValue<T, V, R>().read(apply, title, this, allowEmpty, maxLen);
    }

    /**
     * 消息处理
     *
     * @param message
     */
    public void handlerMessage(String message, Object... params) {
        String msg = StrFormatter.format(message, params);
        if (isThrow) {
            throw new AssertException(msg);
        }
        messages.add(msg);
    }

    /**
     * 校验初始化
     *
     * @param bean
     * @param isThrow
     */
    public AssertorBean(T bean, String label, boolean isThrow) {
        this.bean = bean;
        this.label = label;
        this.isThrow = isThrow;
    }

    public AssertorBean<T> isThrow(boolean isThrow) {
        this.isThrow = isThrow;
        return this;
    }


    public <R> AssertorBean<T> notNull() {
        AssertUtils.notNull(label, bean);
        return this;
    }

    /**
     * 必须为空
     */
    public <R> AssertorBean<T> mustNull() {
        AssertUtils.mustNull(label, bean);
        return this;
    }

    public <V, R> AssertorBean<T> eq(V leftValue, R rightValue, String title) {
        AssertUtils.eq(false, leftValue, rightValue, title);
        return this;
    }

    public <R> AssertorBean<T> eq(SFunction<T, R> getter, R leftValue, String title) {
        R value = getter.apply(bean);
        return eq(leftValue, value, title);
    }

    public <R> AssertorBean<T> isTrue(boolean expression, Consumer<AssertorBean<T>> consumer, String message, Object... params) {
        AssertUtils.isTrue(expression, message, params);
        if (consumer != null) {
            consumer.accept(this);
        }
        return this;
    }

    public <R> AssertorBean<T> isTrue(boolean expression, String message, Object... params) {
        return isTrue(expression, null, message, params);
    }

}
